/**
 * @class OutputPanel
 * @extends Ext.NestedLayoutPanel
 */
var OutputPanel = function(el, config) {
  this.layout = new Ext.BorderLayout(el, {
    north : {
      initialSize : 28
    },
    center: {
      titlebar: false,
      autoScroll : true
    }
  });
  this.toolbarPanel = new Ext.ContentPanel(el.createChild());
  this.toolbar = new Ext.Toolbar(this.toolbarPanel.el.createChild());
  this.textField = new Ext.form.TextField({
    selectOnFocus : true, 
    width : 100
  });
  this.toolbar.add(this.textField);
  this.toolbar.addButton({
    text: 'Refresh',
    cls: 'x-btn-text-icon af-refresh-btn',
    handler: this.refresh,
    scope : this
  });
  this.textField.on('change', function() {
    this.setExpr(this.textField.getValue());
  }, this);

  this.contentPanel = new Ext.ContentPanel(el.createChild());
  this.outputView = new OutputTreeView(this.contentPanel.el.createChild(), 'Output', false); 

  this.layout.add('north', this.toolbarPanel);
  this.layout.add('center', this.contentPanel);

  OutputPanel.superclass.constructor.call(this, this.layout, config);

  this.dropTarget = new Ext.dd.DropTarget(this.el, {
    ddGroup : 'BindingObjectDD',
    overClass : 'af-panel-dragover'
  }); 

  this.dropTarget.notifyOver = this.handleOver.createDelegate(this);
  this.dropTarget.notifyDrop = this.handleDrop.createDelegate(this);
}


Ext.extend(OutputPanel, Ext.NestedLayoutPanel, {
  loadConfig : function(outputExpr) {
    this.setExpr(outputExpr);
  }
  ,
  setExpr : function(expr) {
    this.textField.setValue(expr);
    this.processPanel.processDef.setOutput(expr);
  }
  ,
  refresh : function() {
    this.outputView.prepare();
    this.processPanel.process.start(
      this.outputView.render.createDelegate(this.outputView)
    );
  }
  ,
  handleOver : function(source, event, data) {
    return "x-dd-drop-ok";
  }
  ,
  handleDrop : function(source, event, data) {
    this.setExpr('${'+data.node.path+'}');
    this.refresh();
    this.dropTarget.notifyOut(source, event, data);
    return true;
  }
  ,
  onLayout : function(event) {
    this.el.setSize(event.regions.east.bodyEl.getSize()); 
    this.layout.layout();
  }
  ,
  destroy : function() {
    OutputPanel.superclass.destroy.apply(this, arguments);
  }
});


/**
 * @class ActionsPanel
 * @extends Ext.NestedLayoutPanel
 */
var ActionsPanel = function(el, config) {
  var layout = new Ext.BorderLayout(el, {
    center: {
      titlebar: false,
      autoScroll : true
    }
  });
  this.contentPanel = new Ext.ContentPanel(el.createChild());
  layout.add('center', this.contentPanel);

  ActionsPanel.superclass.constructor.call(this, layout, config);

  this.dropTarget = new Ext.dd.DropTarget(this.el, {
    ddGroup : 'UnitActionDD'
  }); 
  this.dropTarget.notifyOver = this.handleOver.createDelegate(this);
  this.dropTarget.notifyDrop = this.handleDrop.createDelegate(this);
  this.layout.regions.center.bodyEl.on('scroll', this.repaintWidgets, this);
  this.widgets = [];
  this.margin = new WidgetMargin(this.contentPanel.el.createChild({ cls : 'af-wgt-margin' }), null, this);
  this.addEvents({
    'focus' : true
  });
}


Ext.extend(ActionsPanel, Ext.NestedLayoutPanel, {
  loadConfig : function(actionCfgs) {
    mb.lang.forEach(actionCfgs, this.createActionWidget.createDelegate(this));
  }
  ,
  repaintWidgets : function() {
    mb.lang.forEach(this.widgets, function(w) { w.repaint() });
  }
  ,
  handleOver : function(source, event, data) {
    return "x-dd-drop-ok";
  }
  ,
  handleDrop : function(source, event, data) {
    var config = this.getDefaultActionConfig(data.node.uaction);
    if (event.altKey) {
      this.promptActionName(config);
    } else {
      this.createActionWidget(config);
    }
    this.dropTarget.notifyOut(source, event, data);
    return true;
  }
  ,

  promptActionName : function(config) { 
    var _orig = arguments.callee;
    var _arg = arguments;
    Ext.Msg.prompt(
      'Action Name',
      'Please input unique action name',
      function(btn, text) {
        if (btn=="ok") {
          if (/^[a-zA-Z_][0-9a-zA-Z_]*$/.test(text)) {
            this.createActionWidget({ name : text, type : config.type });
          } else {
            _orig.apply(this, _arg);
          } 
        }
      },
      this
    );
    
    // text input focus
    var input = Ext.Msg.getDialog().body.select('input');
    input.focus.createDelegate(input).defer(100);
    input.value = config.name;
  }
  ,
  getDefaultActionConfig : function(uaction) {
    var config = {};
    config.type = uaction.getQualifiedType();
    var namebase = uaction.type.toLowerCase().replace(/[^a-z0-9]/g, '');
    config.name = namebase;
    for (var i=1; this.processPanel.processDef.findActionDef(config.name); i++) {
      config.name = namebase + i;
    } 
    return config;
  }
  ,
  createActionWidget : function(config) {
    var actionDef = new mb.ActionDef(config);
    try {
      this.processPanel.processDef.addActionDef(actionDef);
    } 
	catch (e) {
      return null;
    }
    var uaction = mb.packages.findUnitAction(config.type);
    var widget;
    if (uaction.innerProcess) {
      widget = new ProcessActionWidget(this.contentPanel.el.createChild(), {
        actionDef : actionDef,
        processPanel : this.processPanel,
        innerProcessConfig : config.innerProcess
      });
    } 
	else {
      var Widget = mb.editor.widgets.findWidget(uaction.getQualifiedType()) || ActionWidget;
      widget = new Widget(this.contentPanel.el.createChild(), {
        actionDef : actionDef,
        processPanel : this.processPanel
      });
    }
    widget.on('focus', this.handleFocusWidget, this);
    widget.on('destroy', this.handleDestroyWidget, this);
    this.widgets.push(widget);
    widget.focus();
    return widget;
  }
  ,
  insertWidgetAfter : function(pivot, widget) {
    if (pivot == widget) return;
    widget.el.insertAfter((pivot || this.margin).el.dom);
    var tmpwidgets = [];
    if (!pivot) tmpwidgets.push(widget);
    mb.lang.forEach(this.widgets, function(w) {
      if (w==widget) {
        return;
      }
      tmpwidgets.push(w);
      if (w==pivot) {
        tmpwidgets.push(widget);  
      }
    });
    this.widgets = tmpwidgets;
    this.recalcActionDefOrder();
  }
  ,
  handleFocusWidget : function(widget) {
    mb.lang.forEach(this.widgets, function(wgt) {
      if (wgt!=widget) wgt.blur();
    });
    this.fireEvent('focus', widget);
    this.repaintWidgets();
  }
  ,
  handleDestroyWidget : function(widget) {
    var i = jQuery.inArray(widget, this.widgets);
    this.widgets = jQuery.grep(this.widgets, function(w) {
      return w != widget 
    });
    widget.un('focus', this.handleFocusWidget);
    widget.un('destroy', this.handleDestroyWidget);
    if (i>=this.widgets.length) i = this.widgets.length-1;
    if (i>=0) this.widgets[i].focus();
    this.repaintWidgets();
  } 
  ,
  recalcActionDefOrder : function() {
    mb.lang.forEach(this.widgets, function(widget, i) {
      widget.actionDef.order = i;
    });
  }
  ,
  onLayout : function(event) {
    this.el.setSize(event.regions.center.bodyEl.getSize());
    this.layout.layout();
    //mb.lang.forEach(this.widgets, function(w) { w.adjustSize(); });
  }
  ,
  checkScroll : function(event) {
    if (event.xy[1] - this.contentPanel.el.getTop() < 20) {
      this.contentPanel.el.scroll('up', 10);  
    } else if (this.contentPanel.el.getBottom() - event.xy[1] < 20) {
      this.contentPanel.el.scroll('down', 10);
    } 
  }
  ,
  destroy : function() {
    ActionsPanel.superclass.destroy.apply(this, arguments);
    mb.lang.forEach(this.widgets, function(w) { w.destroy() });
  }
});
